import itertools
import time


class Relation():
    def __init__(self, mongo_client, meet_time, time_interval, reset_time):
        self.data = {}  # camera timestamp [acvs_id]
        self.mongo_client = mongo_client
        # 同行时间
        self.meet_time = meet_time
        self.time_interval = time_interval
        # 重置时间
        self.reset_time = reset_time
        self.latest_time = 0
        self.count_data = {}  # camera acvs_id [tail_acvs_id]

    def handel_logic(self, camera_id, timestamp, acvs_id):
        self.structure_data(camera_id, timestamp, acvs_id)
        dic = {k: list(v) for k, v in self.data[camera_id].items() if
               int(k) in range(timestamp - self.meet_time, timestamp + self.meet_time)}
        # 同行人数
        p_count = self.count_person(dic)

        for tail_timestamp, tail_acvs in dic.items():
            for t in tail_acvs:
                if str(acvs_id) == str(t):
                    continue
                # 排序id 固定小的在前
                ids = [acvs_id, t]
                ids.sort(reverse=False)
                result = {
                    "camera_id": camera_id,
                    "acvs_id": ids[0],
                    "tail_acvs_id": ids[1],
                    "score": self.get_score_by_person_number(
                        self.get_score(int(timestamp), int(tail_timestamp)), p_count)
                }
                self.structure_count(result, timestamp)
                # self.mongo_client.ins_one_relation(result)

                self.mongo_client.update_relation(result)

        time_old = self.latest_time - self.reset_time
        self.del_old_data(time_old)
        self.insert_cache(time_old)

    def del_old_data(self, time_old):
        to_del = []
        for key, value in self.data.items():
            for k in value.keys():
                if int(k) < time_old:
                    to_del.append((key, k))
        for item in to_del:
            self.data.get(item[0]).pop(item[1])

    def structure_data(self, camera_id, timestamp, acvs_id):
        # 判断是否时间过低  不处理此时间
        if self.latest_time < timestamp:
            if self.latest_time - timestamp > self.reset_time:
                return
            else:
                self.latest_time = timestamp
        if self.data.get(camera_id) is None:
            self.data.update({camera_id: {timestamp: {acvs_id: 0}}})
        else:
            if self.data.get(camera_id).get(timestamp) is None:
                self.data[camera_id].update({timestamp: {acvs_id: 0}})
            else:
                if self.data.get(camera_id).get(timestamp).get(acvs_id) is None:
                    self.data[camera_id][timestamp].update({acvs_id: 0})

    def structure_count(self, result, timestamp):
        acvs_id = result.get("acvs_id")
        tail_acvs_id = result.get("tail_acvs_id")
        camera_id = result.get("camera_id")
        score = result.get("score")
        if self.count_data.get(camera_id):
            if self.count_data.get(camera_id).get(acvs_id):
                if self.count_data.get(camera_id).get(acvs_id).get(tail_acvs_id):
                    new_score = self.count_data.get(camera_id).get(acvs_id).get(tail_acvs_id)[0] + score
                    time = self.count_data.get(camera_id).get(acvs_id).get(tail_acvs_id)[1]
                    if time <= timestamp:
                        self.count_data.get(camera_id).get(acvs_id).update({tail_acvs_id: [new_score, timestamp]})
                    else:
                        self.count_data.get(camera_id).get(acvs_id).update({tail_acvs_id: [new_score, time]})
                else:
                    self.count_data.get(camera_id).get(acvs_id)[tail_acvs_id] = [score, timestamp]
            else:
                self.count_data.get(camera_id).update({acvs_id: {tail_acvs_id: [score, timestamp]}})
        else:
            self.count_data[camera_id] = {acvs_id: {tail_acvs_id: [score, timestamp]}}

    def insert_cache(self, time_old):
        to_clear = []
        for camera in self.count_data.keys():
            for acvs_id, tail_acvs_ids in self.count_data.get(camera).items():
                for tail_acvs_id in tail_acvs_ids:
                    if self.count_data.get(camera).get(acvs_id).get(tail_acvs_id)[1] < time_old:
                        data = {
                            "camera_id": camera,
                            "acvs_id": acvs_id,
                            "tail_acvs_id": tail_acvs_id,
                            "score": self.count_data.get(camera).get(acvs_id).get(tail_acvs_id)[0],
                            "timestamp": self.count_data.get(camera).get(acvs_id).get(tail_acvs_id)[1]
                        }
                        # 不再插入 relation
                        # self.mongo_client.ins_one_relation(data)
                        to_clear.append((camera, acvs_id, tail_acvs_id))
        for item in to_clear:
            del self.count_data[item[0]][item[1]][item[2]]

    def get_score(self, timestamp, tail_timestamp):
        return 1 - abs(tail_timestamp - timestamp) * .05

    def get_score_by_person_number(self, score, p_count):
        return score * 2 / p_count

    def count_person(self, data_dic):
        return len(set(list(itertools.chain.from_iterable(list(data_dic.values())))))
